﻿function $se(element, option) {
    var ie = document.all ? true : false;
    function make(t, p, a, s, c) {
        var e = document.createElement(t);
        if (a) { for (var i in a) e.setAttribute(i, a[i]); }
        if (s) { for (var i in s) e.style[i] = s[i]; }
        if (navigator && navigator.userAgent) { // make IE6, IE7 compatible
            var g = navigator.userAgent;
            if (g.indexOf('MSIE 6.0') > 0 || g.indexOf('MSIE 7.0') > 0)
                e = document.createElement(e.outerHTML.replace('\r\n', ''));
        }
        if (p) p.appendChild(e);
        if (c) e.innerHTML = c;
        return e;
    }
    function stopProp(e) {
        if (e.stopPropagation) e.stopPropagation();
        else e.cancelBubble = true;
    }
    function addEvent(o, e, f) {
        if (o.addEventListener) o.addEventListener(e, f);
        else if (o.attachEvent) o.attachEvent('on' + e, f);
    }
    function setStyle(o, s) {
        if (s) { for (var i in s) o.style[i] = s[i]; }
    }
    function setClass(o, c) {
        o.setAttribute('class', c);
        if (ie) o.setAttribute('className', c);
    }
    function removeClass(o) {
        o.removeAttribute('class');
        if (ie) o.removeAttribute('className');
    }
    var that = this;
    this.commands = [
      //[command, text, state]
        ['Undo', 'Undo', 0],
        ['Redo', 'Redo', 0],
        ['Font', 'Font', 0],
        ['FontSize', 'Font Size', 0],
        ['Bold', 'Bold', 1],
        ['Italic', 'Italic', 1],
        ['Underline', 'Underline', 1],
        ['Subscript', 'Subsrpit', 1],
        ['Superscript', 'Superscript', 1],
        ['InsertOrderedList', 'Order List', 1],
        ['InsertUnorderedList', 'Unorder List', 1],
        ['Outdent', 'Outdent', 0],
        ['Indent', 'Indent', 0],
        ['JustifyLeft', 'Justify Left', 0],
        ['JustifyCenter', 'Justify Center', 0],
        ['JustifyRight', 'Justify Right', 0],
        ['RemoveFormat', 'Clear Style', 0],
        ['CreateLink', 'Insert Hyperlink', 0],
        ['InsertImage', 'Insert Image', 0]
    ];
    this.fonts = ['Arial', 'Calibri', 'Century', 'Consolas', 'Segoe UI', 'Tahoma', 'Times New Roman', 'Verdana'];
    this.sizes = [
      //[value, text, size]
        [1, 'smallest', '10px'],
        [2, 'smaller', '12px'],
        [3, 'small', '14px'],
        [4, 'medium', '16px'],
        [5, 'large', '18px'],
        [6, 'larger', '20px'],
        [7, 'largest', '24px']
    ];
    this.id = element;
    this.textarea = document.getElementById(this.id);
    this.textarea.style.display = 'none';
    this.width = 640; this.height = 320; this.style = 'smitheditor'; this.css = 'smitheditor.css'; this.doc = null;
    if (option) { // get options
        if (option.width) this.width = option.width;
        if (option.height) this.height = option.height;
        if (option.style) this.style = option.style;
        if (option.css) this.css = option.css;
    }
    var b = make('div', null, { 'class': this.style }, { 'width': this.width + 'px', 'height': this.height + 'px' }); // border
    this.textarea.parentNode.insertBefore(b, this.textarea);
    var c = make('div', b, { 'class': 'controls' }); // controls
    this.cmdList = make('ul', c);
    for (var i = 0; i < this.commands.length; i++) {
        var m = this.commands[i];        
        var t = make('li', this.cmdList);
        var a = make('a', t, { 'href': '#', 'command': m[0], 'title': m[1], 'hidefocus': '' }, { 'backgroundPosition': (-i * 20) + 'px 0px' });
        a.onclick = function () {
            stopProp(event); 
            that.hideAll();
            var k = this.getAttribute('command');
            if (k == 'Font') that.showFont();
            else if (k == 'FontSize') that.showSize();
            else if (k == 'CreateLink') that.insertLink();
            else if (k == 'InsertImage') that.insertImage();
            else { that.exec(k); }
            return false;
        };
        if (m[0] == 'Font') this.fontItem = t; 
        else if (m[0] == 'FontSize') this.sizeItem = t;
    }
    this.fontList = make('ul', b, { 'class': 'select' }, { 'display': 'none' });
    for (var i = 0; i < this.fonts.length; i++) {
        var t = make('li', this.fontList, { 'class': 'item' });
        var a = make('a', t, { 'href': '#' }, { 'font-family': this.fonts[i] }, this.fonts[i]);
        a.onclick = function () {
            stopProp(event);
            that.exec('FontName', this.style.fontFamily);
            that.hideFont(); 
            return false;
        };
    }
    this.sizeList = make('ul', b, { 'class': 'select' }, { 'display': 'none' });
    for (var i = 0; i < this.sizes.length; i++) {
        var k = this.sizes[i];
        var t = make('li', this.sizeList, { 'class': 'item' });
        var a = make('a', t, { 'href': '#', 'value': k[0] }, { 'font-size': k[2] }, k[1]);
        a.onclick = function () {
            stopProp(event);
            that.exec('FontSize', this.getAttribute('value'));
            that.hideSize(); 
            return false;
        };
    }
    this.editor = make('iframe', null,  { 'class': 'editor', 'frameborder': '0' }, { 'width': this.width + 'px', 'height': this.height - 32 + 'px' });
    this.editor.onload = function () {
        that.doc = that.editor.contentWindow.document;
        var c = '<html><head><link href="' + that.css + '" rel="stylesheet" type="text/css"></head><body contenteditable="true"></body></html>';
        that.doc.write(c);
        that.doc.body.innerHTML = that.textarea.value;
        that.doc.body.setAttribute('contenteditable', 'true');
        that.timer = setInterval(function () { that.tick(); }, 300);
        addEvent(document, 'click', function () { that.hideAll(); });
        addEvent(that.doc, 'click', function () { that.hideAll(); });
    };
    b.appendChild(this.editor);
    this.tick = function () {
        for (var i = 0; i < this.commands.length; i++) {
            var c = this.commands[i], n = this.cmdList.childNodes[i];
            if (c[2]) {
                removeClass(n);
                if (this.doc.queryCommandState(c[0])) setClass(n, 'toggle');
            }
        }
    };
    this.exec = function (c, v) { this.doc.execCommand(c, false, v ? v : null); }
    this.showFont = function () {
        if (this.fon) this.hideFont();
        else {
            var m = this.fontList, n = this.fontItem;
            setClass(n, 'toggle');
            setStyle(m, { 'display': '', 'top': n.offsetTop + n.offsetHeight + 'px', 'left': n.offsetLeft + 'px' });
            this.fon = true;
        }
    }
    this.hideFont = function () {
        if (this.fon) {
            removeClass(this.fontItem); 
            setStyle(this.fontList, { 'display': 'none' });
            this.fon = false;
        }
    }
    this.showSize = function () {
        if (this.son) this.hideSize();
        else {
            var m = this.sizeList, n = this.sizeItem;
            setClass(n, 'toggle');
            setStyle(m, { 'display': '', 'top': n.offsetTop + n.offsetHeight + 'px', 'left': n.offsetLeft + 'px' });
            this.son = true;
        }
    }
    this.hideSize = function () {
        if (this.son) {
            removeClass(this.sizeItem);
            setStyle(this.sizeList, { 'display': 'none' });
            this.son = false;
        }
    }
    this.hideAll = function () {
        this.hideFont(); this.hideSize();
    }
    this.insertLink = function () {
        var s = prompt('URL', 'http://');
        if (s) this.exec('CreateLink', s);
    }
    this.insertImage = function () {
        var s = prompt('Image Source', 'http://');
        if (s) this.exec('InsertImage', s);
    }
}
$se.prototype.text = function () { return this.doc.body.innerText; }
$se.prototype.html = function () { return this.doc.body.innerHTML; }
$se.prototype.post = function () { this.textarea.value = this.html(); }
SmithEditor = $se;